package com.zcq.dm.masking;


import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.BeanProperty;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.ContextualSerializer;
import com.zcq.dm.enums.DMTypeEnum;
import com.zcq.dm.utils.SpringContextUtil;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;

import java.io.IOException;
import java.util.Objects;

@NoArgsConstructor
@AllArgsConstructor
public class DMInfoSerialize extends JsonSerializer<String> implements ContextualSerializer {

    //脱敏的数据类型
    private DMTypeEnum typeEnum;

    @Override
    public void serialize(String value, JsonGenerator gen, SerializerProvider serializers) throws IOException, JsonProcessingException {
        gen.writeString(doMaskIng(value, this.typeEnum));
    }

    private String doMaskIng(String val, DMTypeEnum typeEnum) {
        IDataMasking dataMasking = null;
        try {
            dataMasking = SpringContextUtil.getBean(IDataMasking.class);
        }catch (NoSuchBeanDefinitionException e){}
        if(dataMasking == null){
            return val;
        }
        //是否命中权限脱敏白名单，命中则不脱敏
        if(dataMasking.isHitWhite(typeEnum)){
            return val;
        }
        return typeEnum.getDsMethod().apply(val);
    }

    @Override
    public JsonSerializer<?> createContextual(SerializerProvider prov, BeanProperty property) throws JsonMappingException {
        if(property == null){
            return prov.findNullValueSerializer(property);
        }

        if(!Objects.equals(property.getType().getRawClass(), String.class)) {
            return prov.findValueSerializer(property.getType(), property);
        }

        DMInfo dMInfo = property.getAnnotation(DMInfo.class);
        if(dMInfo == null){
            dMInfo = property.getContextAnnotation(DMInfo.class);
        }
        if (dMInfo != null) {
            return new DMInfoSerialize(dMInfo.type());
        }
        return prov.findValueSerializer(property.getType(), property);
    }


}
